﻿Imports TyranntEngine
Imports DarkGDK
Imports System.IO

Public Class dungeonGeneratorForm

    Private WithEvents _welcome As New TyranntWelcomeService.WelcomeClient
    Private WithEvents _user As New TyranntUserService.TyranntUserServiceClient
    Private WithEvents _dungeon As New TyranntDungeonService.TyranntDungeonServiceClient

    Private _token As String

    Private _currentObject As New dungeonObject
    Private _3dobject As DarkGDK.Basic3D.Object3D
    Private _texture As DarkGDK.Basic2D.Image

    Private _versionMajor As Integer = 0
    Private _versionMinor As Integer = 1
    Private _versoinPatch As Integer = 7

    Private _rotateX As Integer = -1
    Private _rotateY As Integer = -1
    Private _rotateMlt As Single = 0.5
    Private _moveX As Integer = -1
    Private _moveY As Integer = -1

    Private _loadingMazeObjects As Boolean = False

    Private _splash As New contentSplash

    Private Const _texturePath As String = ".\media\textures\"

#Region "General Code"
    Private Sub dungeonGeneratorForm_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        _splash.Show()
        _welcome.HelloAsync(_versionMajor, _versionMinor, _versoinPatch)
    End Sub

    Private Sub _welcome_HelloCompleted(ByVal sender As Object, ByVal e As TyranntWelcomeService.HelloCompletedEventArgs) Handles _welcome.HelloCompleted
        If e.Result.UpdateRequired = True Then
            MessageBox.Show("Please Launch Main Game Client", "An update is required", MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
            Quit()
        End If
        Dim logon As New LogonControl
        If logon.ShowDialog() = Windows.Forms.DialogResult.OK Then
            If logon.UserGroup = 1 Then
                _token = logon.TokenString
                userToolStripLabel.Text = logon.UserAlias
            Else
                MessageBox.Show("You must be and administrator to use this tool", "Permission Denied", MessageBoxButtons.OK, MessageBoxIcon.Error)
                Quit()
            End If
        Else
            Quit()
        End If
        ScanTextures()
        _splash.Close()
        Me.Show()
        Me.Opacity = 100
        Me.Enabled = True
        LoadInitial()
    End Sub

    Private Sub LoadInitial()
        LoadMazeObjects()
        DarkGDK.Camera.BackdropOn()
        DarkGDK.Camera.ColorBackdrop(Color.LightGray)
        InitMazeObject3D()
    End Sub

    Private Sub Quit()
        _splash.Close()
        End
    End Sub

    Public Sub ScanTextures()
        Dim dir As DirectoryInfo = New DirectoryInfo(_texturePath)

        For Each imgFile In dir.GetFiles("*")
            objectTextureComboBox.Items.Add(imgFile.Name)
        Next
    End Sub

    Private Function CheckResult(ByVal result As String, ByVal message As String) As Boolean
        If result.Contains("[#]") = True Then
            MessageBox.Show(result, "Failed to get " + message, MessageBoxButtons.OK, MessageBoxIcon.Error)
            _loadingMazeObjects = False
            EnableObjectForm(True)
            Return False
        Else
            Return True
        End If
    End Function

    Private Sub mainTabControl_Deselected(ByVal sender As Object, ByVal e As System.Windows.Forms.TabControlEventArgs) Handles mainTabControl.Deselected
        Select Case e.TabPageIndex
            Case 0
                CloseMazeObject3D()
            Case 1
                CloseMazeBlock3D()
        End Select
    End Sub

    Private Sub mainTabControl_Selected(ByVal sender As Object, ByVal e As System.Windows.Forms.TabControlEventArgs) Handles mainTabControl.Selected
        Select Case e.TabPageIndex
            Case 0
                InitMazeObject3D()
            Case 1
                InitMazeBlock3D()
        End Select
    End Sub

    Private Sub CtlDarkGDKViewport2_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles CtlDarkGDKViewport2.MouseMove
        Select Case mainTabControl.SelectedIndex
            Case 0
                ObjectProcessMouseMove(e)
            Case 1
                BlockProcessMouseMove(e)
        End Select
    End Sub

#End Region

#Region "Maze Object Routines"

    Private Sub InitMazeObject3D()
        refreshObjectView.Interval = 100
        refreshObjectView.Enabled = True
    End Sub

    Private Sub CloseMazeObject3D()
        ResetObjectForm()
        refreshObjectView.Enabled = False
        ' delete the maze objects
    End Sub

    Private Sub LoadMazeObjects()
        If _loadingMazeObjects = False Then
            EnableObjectForm(False)
            RefreshMazeObjectForm()
            _loadingMazeObjects = True
            _dungeon.GetDungeonObjectsAsync(_token)
        End If
    End Sub

    Private Sub objectNameTextBox_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles objectNameTextBox.TextChanged
        _currentObject.Name = objectNameTextBox.Text
        ValidateObjectForm()
    End Sub

    Private Sub objectDescTextBox_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles objectDescTextBox.TextChanged
        _currentObject.Description = objectDescTextBox.Text
    End Sub

    Private Sub objectModelTypeRadioButton_CheckedChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles objectModelTypeRadioButton.CheckedChanged
        _currentObject.ObjectType = "model"
        objectModelNameComboBox.Enabled = True
        ValidateObjectForm()
    End Sub

    Private Sub objectPlaneTypeRadioButton_CheckedChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles objectPlaneTypeRadioButton.CheckedChanged
        If objectPlaneTypeRadioButton.Checked = True Then
            If IsNothing(_3dobject) = False Then
                _3dobject.Delete()
            End If
            _currentObject.ObjectType = "plane"
            _3dobject = New DarkGDK.Basic3D.Plane(100, 100)
            refreshObjectView.Enabled = True
        End If
        ValidateObjectForm()
    End Sub

    Private Sub objectSphereTypeRadioButton_CheckedChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles objectSphereTypeRadioButton.CheckedChanged
        If objectSphereTypeRadioButton.Checked = True Then
            If IsNothing(_3dobject) = False Then
                _3dobject.Delete()
            End If
            _currentObject.ObjectType = "sphere"
            _3dobject = New DarkGDK.Basic3D.Sphere(100)
            refreshObjectView.Enabled = True
        End If
        ValidateObjectForm()
    End Sub

    Private Sub objectCubeRadioButton_CheckedChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles objectCubeRadioButton.CheckedChanged
        If objectCubeRadioButton.Checked = True Then
            If IsNothing(_3dobject) = False Then
                _3dobject.Delete()
            End If
            _currentObject.ObjectType = "cube"
            _3dobject = New DarkGDK.Basic3D.Cube(100)
            refreshObjectView.Enabled = True
        End If
        ValidateObjectForm()
    End Sub

    Private Sub RefreshMazeObjectForm()
        objectNameTextBox.Text = _currentObject.Name
        objectDescTextBox.Text = _currentObject.Description
        objectModelNameComboBox.Enabled = False
        Select Case _currentObject.ObjectType
            Case "cube"
                objectCubeRadioButton.Checked = True
            Case "model"
                objectModelTypeRadioButton.Checked = True
                objectModelNameComboBox.Enabled = True
                objectModelNameComboBox.Text = _currentObject.ModelName
            Case "plane"
                objectPlaneTypeRadioButton.Checked = True
            Case "sphere"
                objectSphereTypeRadioButton.Checked = True
            Case Else
                objectPlaneTypeRadioButton.Checked = False
                objectCubeRadioButton.Checked = False
                objectSphereTypeRadioButton.Checked = False
        End Select
        objectTextureComboBox.Text = _currentObject.TextureName
        ValidateObjectForm()
    End Sub

    Private Sub refreshObjectView_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles refreshObjectView.Tick
        If DarkGDK.Engine.LoopGDK() Then
            '   Do stuff

            '   Tell DarkGDK.NET to render our default camera display
            DarkGDK.Core.Sync()
        End If
    End Sub

    Private Sub _dungeon_GetDungeonObjectCompleted(ByVal sender As Object, ByVal e As TyranntDungeonService.GetDungeonObjectCompletedEventArgs) Handles _dungeon.GetDungeonObjectCompleted
        If CheckResult(e.Result, "MazeObject") = False Then
            Exit Sub
        End If
        _currentObject.LoadXML(e.Result)
        RefreshMazeObjectForm()
    End Sub

    Private Sub _dungeon_GetDungeonObjectsCompleted(ByVal sender As Object, ByVal e As TyranntDungeonService.GetDungeonObjectsCompletedEventArgs) Handles _dungeon.GetDungeonObjectsCompleted
        If e.Result.Contains("[#]") = True Then
            MessageBox.Show(e.Result, "Failed to get MazeObjects", MessageBoxButtons.OK, MessageBoxIcon.Error)
            _loadingMazeObjects = False
            EnableObjectForm(True)
            Exit Sub
        End If
        dungeonObjectsListView.Items.Clear()
        If e.Result <> "" Then
            Dim sr As New StringReader(e.Result)
            Dim objectsXML As XElement = XElement.Load(sr)
            Dim objects = objectsXML...<mazeObject>
            For Each anObj In objects
                Dim item As New ListViewItem
                Dim objectName As String = anObj.<name>.Value
                Dim objectDesc As String = anObj.<desc>.Value
                Dim objectType As String = anObj.<type>.Value
                item.Text = objectName
                item.SubItems.Add(objectType)
                dungeonObjectsListView.Items.Add(item)
            Next
        End If
        _loadingMazeObjects = False
        EnableObjectForm(True)
    End Sub

    Private Sub objectTextureComboBox_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles objectTextureComboBox.SelectedIndexChanged
        If IsNothing(_3dobject) = False Then
            _texture = New DarkGDK.Basic2D.Image(_texturePath + objectTextureComboBox.Text)
            _currentObject.TextureName = objectTextureComboBox.Text
            _3dobject.Texture = _texture
        End If
    End Sub

    Private Sub ObjectProcessMouseMove(ByVal e As System.Windows.Forms.MouseEventArgs)
        If IsNothing(_3dobject) = False Then
            Select Case e.Button
                Case Windows.Forms.MouseButtons.Left
                    If _rotateX = -1 Then
                        _rotateX = e.X
                        _rotateY = e.Y
                    Else
                        Dim diffX As Integer = _rotateX - e.X
                        Dim diffY As Integer = _rotateY - e.Y
                        _rotateX = e.X
                        _rotateY = e.Y
                        _3dobject.RotateRelative(diffY * _rotateMlt, diffX * _rotateMlt, 0)
                    End If
                    'Case Windows.Forms.MouseButtons.Right
                    '    If _moveX = -1 Then
                    '        _moveX = e.X
                    '        _moveY = e.Y
                    '    Else
                    '        Dim diffX As Integer = _moveX - e.X
                    '        Dim diffY As Integer = _moveY - e.Y
                    '        diffX = diffX - (2 * diffX)
                    '        _moveX = e.X
                    '        _moveY = e.Y
                    '        _3dobject.Position(diffX * _rotateMlt, diffY * _rotateMlt, 0)
                    '    End If
                Case Windows.Forms.MouseButtons.None
                    _rotateX = -1
                    _rotateY = -1
                    _moveX = -1
                    _moveY = -1
            End Select
        End If
    End Sub

    Private Sub EnableObjectForm(ByVal enabled As Boolean)
        objectNewButton.Enabled = enabled
        objectUpdateButton.Enabled = enabled
        objectTypeGroupBox.Enabled = enabled
        If enabled = True Then
            ValidateObjectForm()
        End If
    End Sub

    Private Sub ValidateObjectForm()
        If IsNothing(_currentObject) = True Then
            objectNewButton.Enabled = False
            objectUpdateButton.Enabled = False
        Else
            If _currentObject.IsValid = False Then
                objectNewButton.Enabled = False
                objectUpdateButton.Enabled = False
            Else
                objectNewButton.Enabled = True
                If _currentObject.ID <> -1 Then
                    objectUpdateButton.Enabled = True
                End If
            End If
        End If
    End Sub

    Private Sub objectNewButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles objectNewButton.Click
        EnableObjectForm(False)
        _dungeon.AddDungeonObjectAsync(_token, _currentObject.ToXElement.ToString)
    End Sub

    Private Sub _dungeon_AddDungeonObjectCompleted(ByVal sender As Object, ByVal e As TyranntDungeonService.AddDungeonObjectCompletedEventArgs) Handles _dungeon.AddDungeonObjectCompleted
        If e.Result <> "" = True Then
            MessageBox.Show(e.Result, "Add Dungeon Object Failed", MessageBoxButtons.OK, MessageBoxIcon.Error)
            EnableObjectForm(True)
            Exit Sub
        End If
        ResetObjectForm()
        LoadMazeObjects()
    End Sub

    Private Sub objectUpdateButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles objectUpdateButton.Click
        EnableObjectForm(False)
        _dungeon.UpdateDungeonObjectAsync(_token, _currentObject.ToXElement.ToString)
    End Sub

    Private Sub _dungeon_UpdateDungeonObjectCompleted(ByVal sender As Object, ByVal e As TyranntDungeonService.UpdateDungeonObjectCompletedEventArgs) Handles _dungeon.UpdateDungeonObjectCompleted
        If e.Result <> "" = True Then
            MessageBox.Show(e.Result, "Update Dungeon Object Failed", MessageBoxButtons.OK, MessageBoxIcon.Error)
            EnableObjectForm(True)
            Exit Sub
        End If
        ResetObjectForm()
        LoadMazeObjects()
    End Sub

    Public Sub ResetObjectForm()
        _currentObject = New dungeonObject
        If IsNothing(_3dobject) = False Then
            _3dobject.Delete()
            _3dobject = Nothing
        End If
    End Sub

    Private Sub objectClearButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles objectClearButton.Click
        ResetObjectForm()
    End Sub

    Private Sub dungeonObjectsListView_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles dungeonObjectsListView.SelectedIndexChanged
        If dungeonObjectsListView.SelectedItems.Count > 0 Then
            Dim item As ListViewItem = dungeonObjectsListView.SelectedItems(0)
            Dim objName As String = item.Text
            _dungeon.GetDungeonObjectAsync(_token, objName)
        End If
    End Sub

    Private Sub DeleteObjectToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles DeleteObjectToolStripMenuItem.Click
        Dim name As String = dungeonObjectsListView.SelectedItems(0).SubItems(1).Text
        EnableObjectForm(False)
        _dungeon.DeleteDungeonObjectAsync(_token, name)
    End Sub

#End Region

#Region "Maze Block Routines"

    Private Sub InitMazeBlock3D()
        refreshBlockView.Interval = 100
        refreshBlockView.Enabled = True
    End Sub

    Private Sub CloseMazeBlock3D()
        refreshBlockView.Enabled = False
        ' delete maze block objects
    End Sub

    Private Sub refreshBlockView_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles refreshBlockView.Tick
        If DarkGDK.Engine.LoopGDK() Then
            '   Do stuff

            '   Tell DarkGDK.NET to render our default camera display
            DarkGDK.Core.Sync()
        End If
    End Sub

    Private Sub BlockProcessMouseMove(ByVal e As System.Windows.Forms.MouseEventArgs)

    End Sub

#End Region

End Class
